import sys
import time  # 已导入，无需额外处理
import ubinascii
import urandom


class Topdu:
    def __init__(self, warn_str, phone_number="18538050875"):
        self.warn_str = warn_str    # 警告消息字符串
        self.phone_number = phone_number
        self.SMSC = "+8613800393500"            # 濮阳的SMSC码

    def Send_Message(self):
        # 改用毫秒级计时（关键修改）
        start = time.ticks_ms()  # 获取起始毫秒数

        message = self._to_PDU()
        if message is None:
            print("message, 这竟然是一个空值！")

        pdu = self._to_PDU()
        print(f"pdu : {pdu}")
                    
        # 计算耗时（关键修改）
        end = time.ticks_ms()
        duration_ms = time.ticks_diff(end, start)  # 计算毫秒差值（自动处理溢出）
        print(f"执行时间：{duration_ms}毫秒")
        return ;
        
 
    def __format_message(self):
        str = f"{self.warn_str}"
        return str

                    
    def __to_UCS2(self):
        try:
            message = self.__format_message()
            ucs2_bytes = message.encode('utf-16-be')
            result = bytearray()
            for char in message:
                code_point = ord(char)
                # 基本平面字符（U+0000~U+FFFF）
                if code_point <= 0xFFFF:
                    result.append(code_point >> 8)    # 高8位
                    result.append(code_point & 0xFF)  # 低8位
                # 辅助平面字符（如emoji）需代理对处理
                else:
                    code_point -= 0x10000
                    high_surrogate = 0xD800 | (code_point >> 10)
                    low_surrogate = 0xDC00 | (code_point & 0x3FF)
                    result.append(high_surrogate >> 8)
                    result.append(high_surrogate & 0xFF)
                    result.append(low_surrogate >> 8)
                    result.append(low_surrogate & 0xFF)
            ucs2_bytes = bytes(result)
            ucs2_message_hex =  ubinascii.hexlify(ucs2_bytes).decode('ascii').upper()
            return ucs2_message_hex
        except UnicodeError:
            print("警告信息转换UCS2失败")
        return  
    
    def _to_PDU(self):
        # 处理短信中心号码
        smsc_digits = self.SMSC.replace("+", "")
        if len(smsc_digits) % 2 != 0:
            smsc_digits += "F"  # 奇数长度时补F
        reversed_smsc = self.__reverse_phone_number(smsc_digits)
        smsc = f"0891{reversed_smsc}"

        # 处理手机号码
        phone_digits = self.phone_number.replace("+", "")
        if len(phone_digits) % 2 != 0:
            phone_digits += "F"  # 奇数长度时补F
        reversed_phone = self.__reverse_phone_number(phone_digits)
        original_phone_len = len(phone_digits.replace("F", ""))
        phone_len_hex = f"{original_phone_len:02X}"
        phone_part = f"{phone_len_hex}91{reversed_phone}"

        
        encoded_message = self.__to_UCS2()
        message_bytes_len = len(encoded_message) // 2
        print(f"message_bytes_len:{message_bytes_len}")
        message_bytes_len_hex = f"{message_bytes_len:02X}"

        MAX_SINGLE_MSG = 140  # 单条短信最大字节数
        UDH_LENGTH = 6        # 用户数据头(UDH)占用字节数
        MAX_CONTENT_PER_MSG = MAX_SINGLE_MSG - UDH_LENGTH  # 每片可用内容字节数
        if message_bytes_len <= MAX_SINGLE_MSG:
            tp = f"1100{phone_part}0008B0{message_bytes_len_hex}{encoded_message}"
            tp_length = len(tp) // 2
            pdu = f"{smsc}{tp}"
            result = []
            result.append((pdu, tp_length))
            return result
        
        num_segments = (message_bytes_len + MAX_CONTENT_PER_MSG - 1) // MAX_CONTENT_PER_MSG
        ref_id = urandom.getrandbits(8)  # 生成随机参考号(0-255)
        segments = []  # 存储分片PDU

        for seq in range(1, num_segments + 1):
            start_byte = (seq - 1) * MAX_CONTENT_PER_MSG
            end_byte = min(start_byte + MAX_CONTENT_PER_MSG, message_bytes_len)
            segment_bytes = end_byte - start_byte

            start_index = (seq - 1) * MAX_CONTENT_PER_MSG * 2  # 字符位置(*2因十六进制)
            end_index = start_index + MAX_CONTENT_PER_MSG * 2
            segment_content = encoded_message[start_index:end_index]
            
            # 构建用户数据头(UDH)
            udh = (
                "06"+          # UDH长度=6字节
                "00"+          # IEI: 长短信标识
                "03"+          # IEDL: 后续数据长度
                f"{ref_id:02X}"+        # 参考号
                f"{num_segments:02X}"+   # 总分片数
                f"{seq:02X}"          # 当前分片序号
            )
            
            ud_content = udh + segment_content
            ud_length = len(ud_content) // 2  # 计算总字节数
            
            tp = (
                "1100" +                            # 基本参数
                f"{phone_part}" +                        # 目标地址
                "08" +                              # DCS: UCS2编码
                f"{ud_length:02X}" +          # UDL：用户数据长度
                f"{ud_content}"                           # UD（UDH头 + 短信内容）
            )
            tp_length = len(tp) // 2  # TPDU长度(字节)
            pdu = f"{smsc}{tp}"
            
            segments.append((pdu, tp_length))
        print(f"我发送了长消息: {pdu}, {tp_length}")    
        return segments


    
    def __reverse_phone_number(self,phone_digits):
        reversed_phone = ""
        for i in range(0, len(phone_digits), 2):
            pair = phone_digits[i:i+2]
            reversed_pair = pair[1] + pair[0]
            reversed_phone += reversed_pair
        return reversed_phone
                
 
str = "签到班级:6103\n未到:{absent}/{total}\n时间:{年}年{月}月{日}日 {时}:{分}:{秒}"
print(f"str :\n{str}")
warning = Topdu(str, "18203600458")
warning.Send_Message()